using System;

namespace SG.Ling.AutoTranslator.NLP
{
    public struct CodePointRange : IEquatable<CodePointRange>
    {
        public CodePointRange(uint from, uint to)
        {
            if (from < to)
                throw new ArgumentOutOfRangeException("from", from, @"From must be smaller than To!");

            From = from;
            To = to;
        }

        public readonly uint From;
        public readonly uint To;

        public bool Contains(int number)
        {
            return From <= number && number <= To;
        }

        public override string ToString()
        {
            return string.Format("[{0}..{1}]", From, To);
        }

        #region Equality overloads
        public override bool Equals(object obj)
        {
            return !ReferenceEquals(null, obj) && (obj is CodePointRange && Equals((CodePointRange) obj));
        }

        public bool Equals(CodePointRange other)
        {
            return other.From == From && other.To == To;
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (int) ((From*397) ^ To);
            }
        }

        public static bool operator ==(CodePointRange a, CodePointRange b)
        {
            return a.Equals(b);
        }

        public static bool operator !=(CodePointRange a, CodePointRange b)
        {
            return !(a == b);
        }
        #endregion
    }

    public static class CodePointRangeEx
    {
        private static readonly double Log2 = Math.Log(2);

        public static int NumberOfBits(this int number)
        {
            return (int)Math.Ceiling(Math.Log(number) / Log2);
        }
    }
}